<template>
  <div class="dossierTree_box">
    <select v-model="currDossierID" @change="loadTreeData()" v-if="!dataSource"
            style="margin: 5px 5px 5px 10px;font-size: 14px;outline: none;"
            :style="{width: currDossierID && showDelete ? 'calc(100% - 85px)' : '93%' }">
      <option v-for="item in dossierRootNode" :value="item.NodeID">{{item.MLXSMC}}</option>
    </select>
    <el-button style="width: 60px;height: 23px;padding-top: 5px;padding-left: 16px;margin-top: 5px;" @click="delDossier"
               title="删除选中卷下所有电子卷宗" v-if="currDossierID && showDelete">删除
    </el-button>

    <el-input
      placeholder="输入关键字进行检索"
      size="mini"
      style="width:calc(100% - 20px);margin:5px 10px;font-size: 14px"
      @input="treeFilter"
      v-model="filterText">
    </el-input>
    <el-tree class="dossierTree" ref="dossierTree"
             :data="treeData"
             node-key='NodeID'
             @node-click="nodeClick"
             @check="check"
             :render-content="renderContent"
             :filter-node-method="filterNode"
             :expand-on-click-node="!(pressCtrlKey||pressShiftKey)"
             :highlight-current="true"
             :show-checkbox="showCheckbox">
      <!-- lazy :load="loadChildrenNode" -->
    </el-tree>

    <vmodal :modalshow="modalshow"
            modaltitle="加入示证大纲"
            :closeonclickmodal="false"
            :styleobj="{width: '300px',height: '437px'}"
            @hide="modalshow=false">
      <div slot="modal" style="width:100%;height:100%;background-color: white">
        <div style="width:100%;height:calc(100% - 50px);overflow: auto;">
          <el-tree ref="catalogMLTree"
                   highlight-current
                   render-after-expand
                   :expand-on-click-node="false"
                   node-key='NodeID'
                   :data="catalogML"
                   :props="catalogProps"
                   style="width:100%">
          </el-tree>

          <!-- default-expand-all -->
        </div>
        <div style="text-align: right;height: 50px">
          <el-button style="margin:5px 10px 0 0" size="small" type="plain" @click="cancelAddMindMapping">取消
          </el-button>
          <el-button style="margin:5px 10px 0 0" size="small" type="primary" @click="addMindMapping">确认
          </el-button>
        </div>
      </div>
    </vmodal>

    <div ref="cursor" class="cursor_div">
      <div ref="cursor_img" class="cursor_img"></div>
      <div class="cursor_text nowrap">{{cursor_text}}</div>
    </div>
  </div>
</template>

<script>
  import {mapState, mapGetters} from 'vuex'
  import fs from 'fs'
  import {action, mutation} from '../common/quantity'
  import evidenceCatalogTree from '../config/evidenceCatalogTree'
  import commonServer from '../server/common/commonServer'

  const skin = require('../config/skin')

  const {
    util: {getBase64, getTreeNodes}
  } = require('../util')

  export default {
    name: 'dossierTree',
    data () {
      return {
        currDossierID: '',
        filterText: '',
        cursor_text: '',
        treeData: [],
        pressCtrlKey: false,
        pressShiftKey: false,
        modalshow: false,
        lastCheckedNode: {},
        skin: skin[skin.useSkin],
        catalogProps: {
          children: 'children',
          label: 'alias'
        },
        catalogML: []
      }
    },
    computed: {
      ...mapState({
        dossierDataSource: state => state.appearCourt.dossierDataSource
      }),
      ...mapGetters({
        dossierRootNode: 'dossierRootNode'
      })
    },
    created () {
      if (this.dataSource) return (this.treeData = this.dataSource)
      if (this.dossierRootNode.length) {
        this.currDossierID = this.dossierRootNode[0].NodeID
        this.loadTreeData()
      }
    },
    mounted () {
      this.$eventBus.$on('keyup', ev => {
        if (this.shiftCommand) {
          if (ev.key === 'Shift') this.pressShiftKey = false
        }
        if (this.ctrlCommand) {
          if (ev.key === 'Control') this.pressCtrlKey = false
        }
      })
      this.$eventBus.$on('keydown', ev => {
        if (this.shiftCommand) {
          if (ev.key === 'Shift') this.pressShiftKey = true
        }
        if (this.ctrlCommand) {
          if (ev.key === 'Control') this.pressCtrlKey = true
        }
      })
    },
    methods: {
      cancelAddMindMapping () {
        this.modalshow = false
        this.$refs.catalogMLTree && this.$refs.catalogMLTree.setCurrentNode({})
      },
      addMindMapping () {
        let tree = this.$refs.catalogMLTree
        if (!tree) return
        let node = tree.getCurrentNode()
        tree.setCurrentNode({})
        if (!node) {
          return this.$alert('没有选中节点', '提示', {type: 'warning'})
        }

        let srcTree = this.$refs.dossierTree

        let transferData = srcTree
          .getCheckedNodes()
          .filter(x => x.FileType === 'file')

        if (!transferData.length) transferData.push(this.currentNode.data)

        // 获取所有的文件节点的父节点
        transferData.forEach(item => {
          let node = srcTree.getNode(item)
          if (!node.parent) return
          while ((node = node.parent)) {
            let pnode = node.data
            let isExist = transferData.some(
              _item => _item.NodeID === pnode.NodeID
            )
            if (!isExist) transferData.push(pnode)
            if (pnode.FileType === 'dir') break
          }
        })

        let data = {node: node, dossiers: JSON.stringify(transferData)}

        this.$eventBus.$emit('ADD_FILES_INTO_CATALOG', data)

        this.cancelAddMindMapping()
      },
      treeFilter (value) {
        this.$refs.dossierTree.filter(value)
      },
      async loadTreeData (NodeID) {
        if (this.currDossierID === NodeID) return
        if (NodeID) this.currDossierID = NodeID
        let treeData = await this.$store.dispatch(action.appearCourt.getDossierTreeSource, this.currDossierID)
        this.treeData = JSON.parse(JSON.stringify(treeData))
        this.$store.commit(mutation.common.SaveNodeAllData, this.treeData)
        this.filterText = ''
        this.$emit('rootNodeChanged', this.currDossierID)
      },

      /**
       * tree 树节点点击事件
       * @param data
       * @param node
       * @param c
       * @param ev
       */
      nodeClick (data, node, c, ev = event) {
        /**
         * 去除所有的子节点
         * @param nodes
         * @param pid
         */
        function clearChildNodeByPid (nodes = [], pid) {
          for (let i = 0; i < nodes.length; i++) {
            let node = nodes[i]
            if (node.NodeParentID === pid) {
              if (node.children) {
                clearChildNodeByPid(nodes, node.NodeID)
              }
              nodes.splice(i, 1)
              i--
            }
          }
          return nodes
        }

        /**
         * 获取按住Ctrl时需要勾选的node
         * @param nodes 目前所有选中的节点
         * @param node 需要操作的节点
         * @param cheched 是否选中
         */
        function getCtrlNodes (nodes = [], node, cheched) {
          let index = nodes.findIndex(_node => _node.NodeID === node.NodeID)
          let isExist = index > -1
          if (cheched) {
            if (!isExist) nodes.push(node)
          } else {
            if (isExist) nodes.splice(index, 1)
          }
          return nodes
        }

        /**
         * 获取按住Shift时需要勾选的node
         * @param id1 其中一个ID
         * @param id2 其中一个ID
         * @param treeNodes 数据源
         * @returns {Array}
         */
        let getShiftNodes = (id1, id2, treeNodes = []) => {
          let nodes = []
          let index1 = treeNodes.findIndex(item => item.NodeID === id1)
          let index2 = treeNodes.findIndex(item => item.NodeID === id2)

          if (index2 === -1) index2 = 0
          if (index1 < 0) return nodes
          if (index1 > index2) {
            let temp = index2
            index2 = index1
            index1 = temp
          }
          for (let i = index1; i <= index2; i++) {
            let node = treeNodes[i]
            if (i !== index2 && node.children && node.children.length) continue
            let isExist =
              nodes.findIndex(item => item.NodeID === node.NodeID) > -1
            if (isExist) continue
            nodes.push(node)
          }
          return nodes
        }

        let tree = this.$refs.dossierTree
        let nodes = tree.getCheckedNodes() // 当前所有的选中节点

        if (ev && ev.ctrlKey) {
          this.lastCheckedNode = data
          let p = node
          while ((p = p.parent)) {
            if (p.checked) {
              nodes = nodes.filter(item => item.NodeID !== p.data.NodeID)
            }
          }
          nodes = clearChildNodeByPid(nodes, data.NodeID)
          tree.setCheckedNodes(getCtrlNodes(nodes, data, !node.checked))
          return
        }
        if (ev && ev.shiftKey) {
          let preSetNodes = getShiftNodes(
            data.NodeID,
            this.lastCheckedNode.NodeID,
            this.dossierDataSource
          )
          tree.setCheckedNodes(preSetNodes)
          return
        }

        this.$emit('node-click', data, node, c, ev)
      },
      check (data) {
        this.lastCheckedNode = data
      },
      pointerdown (ev, node, data) {
        if (ev.pointerType === 'touch') return
        if (ev.button) {
          if (ev.button === 2) {
            ev.stopPropagation()
            this.nodeContextmenu(ev, data, node)
          }
          return
        }

        this.isPointerdown = true
        this.isPointerout = false
        console.log('pointerdown')

        let pointerup = ev => {
          this.isPointerdown = false
          this.isPointerout = false
          console.log('pointerup')
          let div = this.$refs.cursor
          div.style.visibility = `hidden`
          this.setTempData()
          this.windowsRemoveEventListener('pointermove', this.pointermove)
          this.windowsRemoveEventListener('pointerup', pointerup)
        }
        this.windowsAddEventListener('pointerup', pointerup)
      },
      pointerout (ev, node, data) {
        ev.returnValue = false
        if (ev.pointerType === 'touch') return

        if (!this.isPointerdown) return
        if (this.isPointerout) return
        console.log('pointerout')
        this.isPointerout = true

        let tree = this.$refs.dossierTree
        tree.setChecked(data, true, true)

        // 获取所有的文件节点
        let transferData = tree
          .getCheckedNodes()
          .filter(x => x.FileType === 'file')

        this.cursor_text = `${transferData.length}个文件`

        // 获取所有的文件节点的父节点
        transferData.forEach(item => {
          let node = tree.getNode(item)
          if (!node.parent) return
          while ((node = node.parent)) {
            let pnode = node.data
            let isExist = transferData.some(
              _item => _item.NodeID === pnode.NodeID
            )
            if (!isExist) transferData.push(pnode)
            if (pnode.FileType === 'dir') break
          }
        })

        this.setTempData({
          type: 'juanzong',
          data: JSON.stringify(transferData)
        })
        this.windowsAddEventListener('pointermove', this.pointermove)
      },
      pointermove (ev) {
        ev.returnValue = false
        if (ev.pointerType === 'touch') return

        let el = ev.target
        let isEvidenceCatalogTree = el.classList.contains('evidenceCatalogTree')
        if (!isEvidenceCatalogTree) {
          while ((el = el.parentElement)) {
            if (el.classList.contains('evidenceCatalogTree')) {
              isEvidenceCatalogTree = true
              break
            }
          }
        }

        let div = this.$refs.cursor
        let cursorImg = this.$refs.cursor_img
        let x = ev.screenX - window.screenX
        let y = ev.screenY - window.screenY - 10 - (window.outerHeight - window.innerHeight)
        x = x - div.offsetWidth / 2
        div.style.left = `${x}px`
        div.style.top = `${y}px`
        div.style.visibility = `visible`
        if (isEvidenceCatalogTree) {
          cursorImg.style.backgroundImage = `url('${getBase64('/img/able.png')}')`
        } else {
          cursorImg.style.backgroundImage = `url('${getBase64('/img/disable.png')}')`
          // div.style.cursor = 'no-drag'
        }
      },
      exportSelectFile () {
      },
      delfun (nodes) {
        let tree = this.$refs.dossierTree
        nodes.forEach(node => {
          if (tree) tree.remove(node)
        })
      },
      // 删除当前卷卷宗材料
      async delDossier () {
        await this.$confirm('是否删除该卷电子卷宗?', '提示')
        let currDossierID = await this.$store.dispatch(action.appearCourt.delDossiers, this.currDossierID)
        if (currDossierID) {
          this.loadTreeData(currDossierID)
        } else {
          this.treeData = []
        }
      },
      async deleteNode (type, data) {
        try {
          let checkedNodes = []
          let tree = this.$refs.dossierTree
          if (!tree) return
          if (!type) {
            checkedNodes = getTreeNodes([data])
          } else if (type === 'file') {
            checkedNodes = tree.getCheckedNodes().filter(node => node.FileType === 'file')
          } else if (type === 'dir') {
            checkedNodes = tree.getCheckedNodes()
          }

          await this.$confirm('是否删除?', '提示')
          this.$store.commit('SET_LOADINGCASE', {loading: true, loadingText: '正在删除电子卷宗，请稍候...'})
          await this.$store.dispatch(action.preplan.DelDossierFile, {
            nodes: checkedNodes,
            type: 'dossier'
          })
          this.delfun(checkedNodes)
          tree.setCheckedNodes([])

          let sendData = {}
          sendData.dossierTreeDataSource = this.treeData
          this.$store.dispatch(action.appearCourt.setDossierTreeSource, {
            id: this.currDossierID,
            data: this.treeData,
            delNode: checkedNodes
          })
          this.$store.commit('SET_LOADINGCASE', {loading: false})
        } catch (e) {
          console.error(e)
        }
      },
      /**
       * 树节点右键事件
       * 右键弹出菜单
       */
      nodeContextmenu (ev, data, node, c) {
        if (!this.showContextmenu) return
        this.currentNode = node
        let tree = this.$refs.dossierTree
        // let isRoot = node.level === 1
        let isFile = data.FileType === 'file'
        let isDir = data.FileType === 'dir'
        let isMulti = tree ? tree.getCheckedNodes().length > 0 : false
        let hasFile = tree
          ? tree.getCheckedNodes().filter(x => x.FileType === 'file').length > 0
          : false

        if (isMulti) {
          // isRoot = false
          isFile = false
          isDir = false
        }

        let contextmenu = [
          {
            label: '删除',
            icon: getBase64('/img/catalog/04.png'),
            show: isDir || isFile,
            click: async () => {
              await this.deleteNode('', data)
            }
          },
          {
            label: '删除选中文件',
            icon: getBase64('/img/catalog/delfile.png'),
            show: isMulti,
            click: async () => {
              await this.deleteNode('file')
            }
          },
          {
            label: '删除选中目录及文件',
            icon: getBase64('/img/catalog/delfolder.png'),
            show: isMulti,
            click: async () => {
              await this.deleteNode('dir')
            }
          },
          {
            label: '导出选中文件内容',
            icon: getBase64('/img/catalog/dc.png'),
            show: isMulti && this.skin.contextmenu.exportSelectFile,
            click: this.exportSelectFile
          },
          {
            label: '加入示证目录',
            icon: getBase64('/img/catalog/dc.png'),
            show: isFile || hasFile,
            click: ev => {
              this.catalogML = evidenceCatalogTree.getCatalogML()
              this.modalshow = true
            }
          },
          {
            label: '保存至本地',
            icon: getBase64('/img/catalog/bc.png'),
            show: isFile,
            click: this.saveLocal
          }
        ]

        this.contextMenuShow(ev, contextmenu)
      },
      renderContent (h, {node, data, store}) {
        return (
          <span
            class={'word14 node_' + data.NodeID}
            style="width:calc(100% - 46px);"
            // draggable
            // onDragstart={() => this.dragStart(event, node, data)}
            onPointerdown={() => this.pointerdown(event, node, data)}
            onPointerout={() => this.pointerout(event, node, data)}
          >
            {data.MLXSMC}
          </span>
        )
      },
      filterNode (value, data, node) {
        if (!value) return true
        if (node.level > 1 && node.parent.visible) return true
        return data.MLXSMC.indexOf(value) !== -1
      },

      getCheckedNodes () {
        let tree = this.$refs.dossierTree
        return tree.getCheckedNodes(...arguments)
      },
      setCheckedNodes () {
        let tree = this.$refs.dossierTree
        return tree.setCheckedNodes(...arguments)
      },
      setChecked () {
        let tree = this.$refs.dossierTree
        return tree.setChecked(...arguments)
      },
      setCurrentNode () {
        let tree = this.$refs.dossierTree
        return tree.setCurrentNode(...arguments)
      },
      getHalfCheckedNodes () {
        let tree = this.$refs.dossierTree
        return tree.getHalfCheckedNodes(...arguments)
      },
      remove () {
        let tree = this.$refs.dossierTree
        return tree.remove(...arguments)
      },
      getNode () {
        let tree = this.$refs.dossierTree
        return tree.getNode(...arguments)
      },
      filter () {
        let tree = this.$refs.dossierTree
        return tree.filter(...arguments)
      },
      getCurrentNode () {
        let tree = this.$refs.dossierTree
        return tree.getCurrentNode(...arguments)
      },
      getSelectedNodes: function (status) {
        let tree = this.$refs.dossierTree
        let dataSource = this.$refs.dossierTree.getCheckedNodes(false, true)
        tree.setCheckedKeys([])
        return dataSource
      },
      async saveLocal () {
        let self = this
        if (!this.currentNode || !this.currentNode.data) return
        let node = this.currentNode.data
        let base64Data = await commonServer.getPDFFileByID(node.ID)
        let res = this.$electron.remote.dialog.showSaveDialog(this.$electron.remote.BrowserWindow.getFocusedWindow(), {
          title: '导出文件内容',
          defaultPath: node.MLXSMC,
          filters: [{name: 'PDF', extensions: ['pdf']}]
        })
        if (!res) return
        base64Data = base64Data.replace(/^data:application\/pdf;base64,/, '')
        let dataBuffer = Buffer.from(base64Data, 'base64')
        fs.writeFile(res, dataBuffer, function (err) {
          if (err) {
            self.$alert('保存错误')
            self.$logger.error(err)
          } else {
            self.$alert('保存成功')
          }
        })
      }
    },
    props: {
      showCheckbox: {
        type: Boolean,
        default: false
      },
      showContextmenu: {
        type: Boolean,
        default: true
      },
      ctrlCommand: {
        type: Boolean,
        default: true
      },
      shiftCommand: {
        type: Boolean,
        default: true
      },
      dataSource: {type: Array},
      showDelete: {
        type: Boolean,
        default: true
      }
    }
  }
</script>

<style scoped lang="scss">
  .dossierTree_box {
    width: 100%;
    height: 100%;

    .dossierTree {
      height: calc(100% - 76px);
      overflow-y: auto;
    }

    .cursor_div {
      position: fixed;
      width: 100px;
      /*height: 50px;*/
      left: 0;
      top: 0;
      z-index: 999999;
      visibility: hidden;
      text-align: center;
      pointer-events: none;

      .cursor_text {
        font-size: 12px;
        color: white;
        text-align: center;
        background-color: rgba(0, 0, 0, 0.3);
        display: inline-block;
        padding-right: 10px;
        padding-left: 10px;
      }

      .cursor_img {
        height: 16px;
        width: 16px;
        background-size: 14px;
        margin-right: 5px;
        display: inline-block;
        background-position: center;
        background-repeat: no-repeat;
        /*margin-left: 20px;*/
      }
    }
  }


</style>
